package com.example.canteen.service;

import com.example.canteen.converter.OrderConverter;
import com.example.canteen.converter.SetMealConverter;
import com.example.canteen.dao.*;
import com.example.canteen.dto.DishDTO;
import com.example.canteen.dto.OrderDTO;
import com.example.canteen.dto.SetMealDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class OrderServiceImpl implements OrderService {
    @Autowired
    OrderRepository orderRepository;
    @Autowired
    DishRepository dishRepository;
    @Autowired
    SetMealRepository setMealRepository;
    @Autowired
    PrivateRoomRepository privateRoomRepository;

    @Override
    public Long addOrder(OrderDTO orderDTO) {
        // 检查订单是否已存在
        if (orderRepository.findByName(orderDTO.getName()) != null) {
            throw new RuntimeException("Order already exists");
        }

        // 获取并持久化私有房间
        PrivateRoom privateRoom = privateRoomRepository.findByName(orderDTO.getPrivateRoomName());
        if (privateRoom == null) {
            throw new RuntimeException("Private room not found");
        }
        // 创建并保存订单
        Order order = OrderConverter.convertOrder(orderDTO);
        order.setPrivateRoom(privateRoom);
        orderDTO.setId(orderRepository.save(order).getId());
        for (String setMealName : orderDTO.getSetMealCount().keySet()) {
            SetMeal setMeal = setMealRepository.findByName(setMealName);
            if (setMeal != null) {
                orderRepository.insertOrderSetMeal(orderDTO.getId(), setMeal.getId(), orderDTO.getSetMealCount().get(setMealName));

            }
        }

        for (String dishName : orderDTO.getDishCount().keySet()) {
            Dish dish = dishRepository.findByName(dishName);
            if (dish != null) {
                orderRepository.insertOrderDish(orderDTO.getId(), dish.getId(), orderDTO.getDishCount().get(dishName));
            }
        }

        return orderDTO.getId();
    }

    @Override
    public Set<OrderDTO> getAllOrders() {
        Set<OrderDTO> orderDTOS = new HashSet<>();
        for (Order order : orderRepository.findAll()) {
            Map<String, Integer> dishCount = new HashMap<>();
            for (Dish dish : dishRepository.findAllById(orderRepository.findDishIdByOrderId(order.getId()))) {
                Integer quantity = orderRepository.findQuantityByOrderIdAndDishId(order.getId(), dish.getId());
                dishCount.put(dish.getName(), quantity);
            }
            Map<String, Integer> setMealCount = new HashMap<>();
            for (SetMeal setMeal : setMealRepository.findAllById(orderRepository.findSetMealIdByOrderId(order.getId()))) {
                Integer quantity = orderRepository.findQuantityByOrderIdAndSetMealId(order.getId(), setMeal.getId());
                setMealCount.put(setMeal.getName(), quantity);
            }
            OrderDTO orderDTO = OrderConverter.convertOrder(order);
            orderDTO.setDishCount(dishCount);
            orderDTO.setSetMealCount(setMealCount);
            orderDTOS.add(orderDTO);
        }
        return orderDTOS;
    }

    @Override
    public OrderDTO updateOrder(long id, String name, String date, String privateRoomName, Map<String, Integer> dishCount, Map<String, Integer> setMealCount) {
        Order orderInDB = orderRepository.findById(id).orElseThrow(
                () -> new IllegalArgumentException("Order not found")
        );

        // 先处理订单基本信息的更新
        if (StringUtils.hasLength(name) &&!name.equals(orderInDB.getName())) {
            orderInDB.setName(name);
        }
        if (StringUtils.hasLength(date) &&!date.equals(orderInDB.getDate())) {
            orderInDB.setDate(date);
        }
        if (privateRoomName!= null &&!privateRoomName.equals(orderInDB.getPrivateRoom().getName())) {
            orderInDB.setPrivateRoom(privateRoomRepository.findByName(privateRoomName));
        }

        // 获取数据库中当前订单已有的菜品ID集合
        Set<Long> dishIdsInDB = orderRepository.findDishIdByOrderId(id);

        // 获取数据库中当前订单已有的套餐ID集合
        Set<Long> setMealIdsInDB = orderRepository.findSetMealIdByOrderId(id);

        // 处理菜品信息和数量的更新及删除操作
        if (dishCount!= null) {
            for (String dishName : dishCount.keySet()) {
                Dish dish = dishRepository.findByName(dishName);
                if (dish!= null) {
                    if (orderRepository.findQuantityByOrderIdAndDishId(id, dish.getId())!= null) {
                        orderRepository.updateQuantityByOrderIdAndDishId(id, dish.getId(), dishCount.get(dishName));
                    } else {
                        orderRepository.insertOrderDish(id, dish.getId(), dishCount.get(dishName));
                    }
                    // 如果成功处理了该菜品，从已有的菜品ID集合中移除它的ID
                    dishIdsInDB.remove(dish.getId());
                }
            }
        }

        // 删除剩余在数据库中但不在传入的dishCount中的菜品
        for (Long dishId : dishIdsInDB) {
            orderRepository.deleteOrderDish(id, dishId);
        }

        // 处理套餐信息和数量的更新及删除操作
        if (setMealCount!= null) {
            for (String setMealName : setMealCount.keySet()) {
                SetMeal setMeal = setMealRepository.findByName(setMealName);
                if (setMeal!= null) {
                    if (orderRepository.findQuantityByOrderIdAndSetMealId(id, setMeal.getId())!= null) {
                        orderRepository.updateQuantityByOrderIdAndSetMealId(id, setMeal.getId(), setMealCount.get(setMealName));
                    } else {
                        orderRepository.insertOrderSetMeal(id, setMeal.getId(), setMealCount.get(setMealName));
                    }
                    // 如果成功处理了该套餐，从已有的套餐ID集合中移除它的ID
                    setMealIdsInDB.remove(setMeal.getId());
                }
            }
        }

        // 删除剩余在数据库中但不在传入的setMealCount中的套餐
        for (Long setMealId : setMealIdsInDB) {
            orderRepository.deleteOrderSetMeal(id, setMealId);
        }

        return OrderConverter.convertOrder(orderRepository.save(orderInDB));
    }
}